//============================================================================
// Copyright (C) 2010 Brett R. Jones
// All Rights Reserved
//
// You may redistribute and/or modify for non commercial and commercial uses
// provided this copyright notice remains in place and is not modified
//
// This code is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================
#include "VxIrrLib.h"

//------------------------------------------------------------------------------
//=== constructor ===//
VxIrrBase::VxIrrBase()
	: m_iScnSizeX(0)		// screen width
	, m_iScnSizeY(0)		// screen height
	, m_u32LastMs(0)
	, m_u32MsElapsedThisFrame(0)
	, m_v3fZeroOrigin(0.0f, 0.0f, 0.0f) 			// 3d vector with all zeros
	, m_v3fNormalXY(0.0f, 0.0f, 1.0f) 				// 3d normal for x-y plane
	, m_oPlaneXY( m_v3fZeroOrigin, m_v3fNormalXY)	// x-y plane
	, m_v3fNormalXZ(0.0f, 1.0f, 0.0f) 				// 3d normal for x-z plane
	, m_oPlaneXZ( m_v3fZeroOrigin, m_v3fNormalXZ)			// x-z plane used for mouse intersect x-y plane
	, m_poPhysBase(0)
	, m_iGameInstance(0)
	, m_iGameLevel(0)
	, m_iGameScore(0)
	, m_iGameBonusPoints(0)		
	, m_iGameTime(0)
	, m_u32GameTimeMs(0)
	, m_iGameHits(0)			// how many times impacted earth land
	, m_iGameMisses(0)			// how many times impacted earth sea
	, m_iGamePercentComplete(0)				// percentage of game completed
	, m_bNeedProgressUpdate(0)
{
	// empty
}
//------------------------------------------------------------------------------
//=== destructor ===//
VxIrrBase::~VxIrrBase()
{

}

//------------------------------------------------------------------------------
//! initialize
#ifdef WIN_PLATFORM
RCODE VxIrrBase::IrrBaseStartup( HWND hWnd, int iScnSizeX, int iScnSizeY )
{
	m_iScnSizeX = iScnSizeX;	// screen width
	m_iScnSizeY = iScnSizeY;	// screen height
	m_hWnd		= hWnd;
	irr::SIrrlichtCreationParameters param;
	param.WindowId = (void *)hWnd;
	param.DriverType = irr::video::EDT_OPENGL;
	param.WindowSize = irr::core::dimension2d<irr::u32>(iScnSizeX, iScnSizeY);
	param.Bits = 16;
	param.Fullscreen = false;
	param.Stencilbuffer = false;
	param.Vsync = false;
	param.EventReceiver = 0; // reciever will get set later on after game is created
	m_poDevice = irr::createDeviceEx( param );
#else // android
RCODE VxIrrBase::IrrBaseStartup( int iScnSizeX, int iScnSizeY )
{
	m_iScnSizeX = iScnSizeX;	// screen width
	m_iScnSizeY = iScnSizeY;	// screen height

	m_poDevice = irr::createDevice( IsGLES2Enabled() ? irr::video::EDT_OGLES2 : irr::video::EDT_OGLES1, 
									irr::core::dimension2d<irr::u32>(iScnSizeX, iScnSizeY), 
									16,
			                        false, false, false, 0);
#endif
    if(NULL == m_poDevice)
    {
        log_msg( LOG_ERROR, "ERROR.. NULL Irrlicht Device\n");
    	return -1;
    }

	log_msg( LOG_INFO, "createDevice r=%d\n", m_poDevice);

	m_poDriver = m_poDevice->getVideoDriver();
    log_msg( LOG_INFO,  "getVideoDriver r=%d\n", m_poDriver);

    m_poSceneMgr = 	m_poDevice->getSceneManager();
    log_msg( LOG_INFO, "getSceneManager r=%d\n", m_poSceneMgr);
    m_poGui = 		m_poDevice->getGUIEnvironment();
    log_msg( LOG_INFO,  "getGUIEnvironment r=%d\n", m_poGui);
    m_poCollideMgr = m_poSceneMgr->getSceneCollisionManager();
    log_msg( LOG_INFO,  "getSceneCollisionManager r=%d\n", m_poCollideMgr);

	m_poTimer =		m_poDevice->getTimer();
    log_msg( LOG_INFO,  "getTimer r=%d", m_poTimer);
	//m_poDefaultFont	= m_poGui->getFont(GetAssetPathAndName( "fonthaettenschweiler.bmp", eGameAssetTypeGui ));
	//m_poDefaultFont	= m_poGui->getFont(GetAssetPathAndName( "font_large.xml", eGameAssetTypeGui ));
	m_poDefaultFont	= m_poGui->getFont(GetAssetPathAndName( "bigfont.png", eGameAssetTypeGui ));
    log_msg( LOG_INFO,  "getFont r=%d", m_poDefaultFont);
	return 0;
}

//------------------------------------------------------------------------------
//! prepare for destruction
void VxIrrBase::IrrBaseShutdown( void )
{
	if( m_poDevice )
	{
		m_poDevice->drop();
		m_poDevice = NULL;
	}
}

//------------------------------------------------------------------------------
//! video suface was lost.. need complete restart of irrlich
RCODE VxIrrBase::IrrBaseRestart( void )
{
	IrrBaseShutdown();
	#ifdef WIN_PLATFORM
		RCODE rc = IrrBaseStartup( m_hWnd, m_iScnSizeX, m_iScnSizeY );
	#else
		RCODE rc = IrrBaseStartup( m_iScnSizeX, m_iScnSizeY );
	#endif // WIN_PLATFORM
	if( rc )
	{
		log_msg( 0, "VxIrrBase::IrrBaseRestart: ERROR %d\n", rc );
	}
	// let derived class do any required restart actions
	return OnIrrlichtRestart();
}


//------------------------------------------------------------------------------
//=== skybox functions ===//
//------------------------------------------------------------------------------
//! set skybox
RCODE VxIrrBase::SetSkyBox(	const irr::c8 * pSkyLeftFileName,	// file name of skybox left texture
							const irr::c8 * pSkyRightFileName,	// file name of skybox right texture
							const irr::c8 * pSkyFrontFileName,	// file name of skybox front texture
							const irr::c8 * pSkyBackFileName,	// file name of skybox Back texture
							const irr::c8 * pSkyUpFileName,		// file name of skybox up texture
							const irr::c8 * pSkyDownFileName )	// file name of skybox down texture
{
	irr::video::ITexture *	poTexSkyBoxUp		= m_poDriver->getTexture( pSkyUpFileName );
	irr::video::ITexture *	poTexSkyBoxDn		= m_poDriver->getTexture( pSkyDownFileName );
	irr::video::ITexture *	poTexSkyBoxLeft		= m_poDriver->getTexture( pSkyLeftFileName );
	irr::video::ITexture *	poTexSkyBoxRight	= m_poDriver->getTexture( pSkyRightFileName );
	irr::video::ITexture *	poTexSkyBoxFront	= m_poDriver->getTexture( pSkyFrontFileName );
	irr::video::ITexture *	poTexSkyBoxBack		= m_poDriver->getTexture( pSkyBackFileName );

	irr::scene::ISceneNode *	poSkyBoxNode = m_poSceneMgr->addSkyBoxSceneNode( poTexSkyBoxUp,
							poTexSkyBoxDn,
							poTexSkyBoxLeft,
							poTexSkyBoxRight,
							poTexSkyBoxFront,
							poTexSkyBoxBack );
	if( poSkyBoxNode )
	{
		return 0;
	}
	log_msg( 0, "Failed to load skybox\n" );
	return -1;

}

//------------------------------------------------------------------------------
//! add smoke style trail to scene node
irr::scene::IParticleSystemSceneNode * VxIrrBase::AddCometTrailParticleSystem( irr::scene::ISceneNode * poSceneNode, const char * pTextureFile, float f32Scale )
{
	// add particle system
	irr::scene::IParticleSystemSceneNode * poParticleSystem = m_poSceneMgr->addParticleSystemSceneNode(false, poSceneNode);
	//log_msg( 0, "VxIrrBase::AddCometTrailParticleSystem: poParticleSystem %d\n", poParticleSystem );
	// create and set emitter
	irr::scene::IParticleEmitter* poParticleEmitter = poParticleSystem->createBoxEmitter(
					irr::core::aabbox3d<irr::f32>(-3.0 * f32Scale, 0, -3.0 * f32Scale, 3 * f32Scale, 1, 3 * f32Scale ),
					irr::core::vector3df(0.0f,0.03f,0.0f),
					40 * f32Scale, 50 * f32Scale,
					irr::video::SColor(0,255,255,255),
					irr::video::SColor(0,255,255,255),
					200 * f32Scale, 550 * f32Scale );
	//log_msg( 0, "VxIrrBase::AddCometTrailParticleSystem: poParticleEmitter %d\n", poParticleEmitter );
	poParticleEmitter->setMinStartSize(irr::core::dimension2d<irr::f32>(20.0f * f32Scale, 30.0f * f32Scale));
	poParticleEmitter->setMaxStartSize(irr::core::dimension2d<irr::f32>(20.0f * f32Scale, 30.0f * f32Scale));

	poParticleSystem->setEmitter(poParticleEmitter);
	poParticleEmitter->drop();

	// create and set affector
	irr::scene::IParticleAffector* poParticleAffector = poParticleSystem->createFadeOutParticleAffector();
	//log_msg( 0, "VxIrrBase::AddCometTrailParticleSystem: poParticleAffector %d\n", poParticleAffector );
	poParticleSystem->addAffector(poParticleAffector);
	poParticleAffector->drop();

	//log_msg( 0, "VxIrrBase::AddCometTrailParticleSystem: loading texture %s\n", pTextureFile );
	irr::video::ITexture * poTex = m_poDriver->getTexture( GetAssetPathAndName( pTextureFile, eGameAssetTypeTexture ) );
	// adjust some material settings
	poParticleSystem->setMaterialFlag(irr::video::EMF_LIGHTING, false);
	poParticleSystem->setMaterialFlag(irr::video::EMF_ZWRITE_ENABLE, false);
	poParticleSystem->setMaterialTexture(0, poTex);
	poParticleSystem->setMaterialType(irr::video::EMT_TRANSPARENT_VERTEX_ALPHA);
	//poParticleSystem->setMaterialType(irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL);

	//log_msg( 0, "VxIrrBase::AddCometTrailParticleSystem: poParticleSystem %d\n", poParticleSystem );
	return poParticleSystem;
}
//------------------------------------------------------------------------------
//! get rectangle centered about a point
irr::core::rect<irr::s32> VxIrrBase::GetCenteredRect( int iPosX, int iPosY, int iWidth, int iHeight)
{
	return irr::core::rect<irr::s32>(iPosX - (iWidth >> 1), iPosY - (iHeight >> 1), iPosX + (iWidth >> 1), iPosY + (iHeight >> 1));
}

//------------------------------------------------------------------------------
//! show message on screen for the given time
void VxIrrBase::ShowTimedMessage( const irr::core::vector3df& v3fPos, const char * pMsg, int iSeconds, irr::u32 u32Color )
{
	// convert message to wide text
	if( NULL == pMsg )
	{
		return;
	}
	irr::core::stringw strText = L"Test";
	strText.Format("%s", pMsg );

	irr::core::dimension2d<irr::u32>	dimText = m_poDefaultFont->getDimension( strText.c_str() );
	irr::core::position2d<irr::s32> m_v2dScreenPos;
	WorldToScreen(	v3fPos, m_v2dScreenPos );
	irr::core::rect<irr::s32> textPos = GetCenteredRect( m_v2dScreenPos.X, m_v2dScreenPos.Y, dimText.Width, dimText.Height );

	m_aTimedMessages.push_back( TimedMessage() );
	TimedMessage * timedMsg = &(m_aTimedMessages[m_aTimedMessages.size() -1]);
	timedMsg->m_iShowTimeSeconds = iSeconds;

	timedMsg->m_poTextNode = m_poGui->addStaticText( strText.c_str(), textPos, false, false );
	if( timedMsg->m_poTextNode )
	{
		timedMsg->m_poTextNode->setOverrideFont( m_poDefaultFont );
		timedMsg->m_poTextNode->setOverrideColor( u32Color );
	}
	else
	{
		log_msg( LOG_DEBUG, "ShowTimedMessage ERROR text node is NULL\n"  );
	}
}

//------------------------------------------------------------------------------
//! clear out any timed message
void VxIrrBase::ClearTimedMessages( void )
{
	m_aTimedMessages.clear();
}

//------------------------------------------------------------------------------
//! called once per second during game play
void VxIrrBase::GamePlayOncePerSecond( void )
{
	m_iGameTime++;
	if( m_aTimedMessages.size() )
	{
		std::vector<TimedMessage>::iterator iter;
		for( iter = m_aTimedMessages.begin(); iter != m_aTimedMessages.end(); ++iter )
		{
			(*iter).m_iShowTimeSeconds--;
			if( 0 >= (*iter).m_iShowTimeSeconds  )
			{
				(*iter).removeTextFromScene();
			}
		}
		bool erased = true;
		while( erased )
		{
			erased = false;
			for( iter = m_aTimedMessages.begin(); iter != m_aTimedMessages.end(); ++iter )
			{
				if( 0 >= (*iter).m_iShowTimeSeconds  )
				{
					m_aTimedMessages.erase( iter );
					erased = true;
					break;
				}
			}
		}
	}
}
